#pragma once

#include <map>
#include <unordered_map>
#include "../inc/protobuf.h"
#include "publish_inft.h"

class DataItem : public IDataItem
{
private:
	int mKey;
	MsgExpress::DataType mType;
	std::vector<std::string> vecValues;
public:
	DataItem(int key,MsgExpress::DataType type);
	virtual ~DataItem();
	void AddValue(std::string value);
	const std::vector<std::string>& GetValues()const;
public:
	virtual int GetKey()const;
	virtual MsgExpress::DataType GetType()const;
	virtual int GetDataNumber()const;

	virtual std::string GetString(int index=0)const;
	virtual std::string GetRaw(int index=0)const;
	virtual int GetInt32(int index=0)const;
	virtual unsigned int GetUInt32(int index=0)const;
	virtual int64_t GetInt64(int index=0)const;
	virtual uint64_t GetUInt64(int index=0)const;
	virtual float GetFloat(int index=0)const;
	virtual double GetDouble(int index=0)const;
	virtual time_t GetDatetime(int index=0)const;
};

class IPublish
{
public:
	virtual ~IPublish(){}
public:
	virtual void SetTopic(int topic)=0;
	virtual int GetTopic()const=0;
	virtual void GetSubIds(std::vector<int>& Ids)const=0;

	virtual bool AddString(int key,std::string value)=0;
	virtual bool AddRaw(int key,const char * str,size_t size)=0;
	virtual bool AddInt32(int key,int value)=0;
	virtual bool AddUInt32(int key,unsigned int value)=0;
	virtual bool AddInt64(int key,int64_t value)=0;
	virtual bool AddUInt64(int key,uint64_t value)=0;
	virtual bool AddFloat(int key,float value)=0;
	virtual bool AddDouble(int key,double value)=0;
	virtual bool AddDatetime(int key,time_t value)=0;

	virtual const void GetKeys(std::vector<int>& Keys)const=0;
	virtual const IDataItem* GetDataItem(int key)const=0;
    
    virtual void SetPubData(const MsgExpress::PublishData& pub)=0;
	virtual void GetPubData(MsgExpress::PublishData& pub)const=0;
};

MSGEXPRESS_API IPublish* CreatePublish(int topic);
MSGEXPRESS_API void FreePublish(IPublish*);

class PublishData : public IPublish
{
private:
	int mTopic;
	std::vector<int> mIds;
	std::unordered_map<int,DataItem*>* mapKeyValues;


private:
	PublishData();
	bool AddValue(int key,MsgExpress::DataType type,std::string value);
public:
	PublishData(int topic);
	virtual ~PublishData();

	virtual void SetPubData(const MsgExpress::PublishData& pub);
	virtual void GetPubData(MsgExpress::PublishData& pub)const;
public:
	virtual void SetTopic(int topic);
	virtual int GetTopic()const;
	virtual void GetSubIds(std::vector<int>& Ids)const;

	virtual bool AddString(int key,std::string value);
	virtual bool AddRaw(int key,const char * str,size_t size);
	virtual bool AddInt32(int key,int value);
	virtual bool AddUInt32(int key,unsigned int value);
	virtual bool AddInt64(int key,int64_t value);
	virtual bool AddUInt64(int key,uint64_t value);
	virtual bool AddFloat(int key,float value);
	virtual bool AddDouble(int key,double value);
	virtual bool AddDatetime(int key,time_t value);

	virtual const void GetKeys(std::vector<int>& Keys)const;
	virtual const IDataItem* GetDataItem(int key)const;
};

class PublishHelper : public IPublishHelper
{
private :
	bool loaded;
	MsgExpress::PublishData* pub;
	MsgExpress::SubscribeData* sub;
	std::unordered_map<int,MsgExpress::DataItem*> mapItems;
private:
	PublishHelper(){}
	MsgExpress::DataItem* CreateItem(int key,MsgExpress::DataType type);
public:
	PublishHelper(MsgExpress::PublishData* pub,bool load);
	PublishHelper(MsgExpress::SubscribeData* sub);
	virtual ~PublishHelper();
public:
	virtual bool AddString(int key,const std::string& value);
	virtual bool AddBinary(int key,const void * value,size_t size);
	virtual bool AddInt32(int key,int value);
	virtual bool AddUInt32(int key,unsigned int value);
	virtual bool AddInt64(int key,int64_t value);
	virtual bool AddUInt64(int key,uint64_t value);
	virtual bool AddFloat(int key,float value);
	virtual bool AddDouble(int key,double value);
	virtual bool AddDatetime(int key,time_t value);
	virtual bool AddBool(int key,bool value);
	virtual bool AddComplex(int key,int64_t a,const std::string& b);
	virtual MsgExpress::DataItem* GetItem(int key);
};
